package in.kmb.inval;



import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;


/**
 * A custom {@code View} implementation which uses drawBitmap to create the Battery graphic.
 * @author Kiran Rao
 *
 */
public class CustomBatteryView extends View {
    
    /*
     * Bounds for frame and content.
     */
    private Rect mOriginalRect, mResizedRect;
    
    /*
     * Bitmaps for frame and content.
     */
    private Bitmap mBitmapFrame, mBitmapContent;
    
    /*
     * Original width and height.
     */
    private int mHeight, mWidth;
    
    /**
     * The last known percentage level of the battery.
     */
    private int mPercent;
    
    /*
     * Paint objects.
     */
    private Paint mPaintFrame, mPaintContent;

    public CustomBatteryView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
    }

    public CustomBatteryView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public CustomBatteryView(Context context) {
        super(context);
        init(context, null);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        
        /*
         * TODO: BUG!
         * 
         * For some reason, even though mPercent is initialized to 100 in init(),
         * when we reach this method, it is reset to zero.
         * 
         *  Because of this, the battery graphic shows as empty at first.
         *  Need to debug this.
         */
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }

    /**
     * Measure width.
     * 
     * @param measureSpec the measure spec
     * @return The width of the view, honoring constraints from measureSpec
     */
    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else {
            // Measure the graphic width
            result = mOriginalRect.width();
            if (specMode == MeasureSpec.AT_MOST) {
                // Respect AT_MOST value if that was what is called for by
                // measureSpec
                result = Math.min(result, specSize);
            }
        }
        
        return result;
    }

    /**
     * Determines the height of this view.
     * 
     * @param measureSpec A measureSpec packed into an int
     * @return The height of the view, honoring constraints from measureSpec
     */
    private int measureHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else {
            // Measure the graphic height
            result = mOriginalRect.height();
            if (specMode == MeasureSpec.AT_MOST) {
                // Respect AT_MOST value if that was what is called for by
                // measureSpec
                result = Math.min(result, specSize);
            }
        }
        
        
        return result;
    }
    
    private void init(Context context, AttributeSet attrs){
        
        /*
         * Get the initial percent value from XML attribute.
         * Defined in /res/values/attrs.xml
         * 
         * Syntax for the attribute is custbattery:percent="100"
         */
        if (context != null && attrs != null){
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Battery);
            this.mPercent = a.getInt(R.styleable.Battery_percent, this.mPercent);
        }
        
        //Initialize the paint objects.
        mPaintFrame = mPaintContent = new Paint();
        
        //Initialize the bitmaps.
        mBitmapContent = BitmapFactory.decodeResource(getResources(), R.drawable.content);
        mBitmapFrame = BitmapFactory.decodeResource(getResources(), R.drawable.frame);
        
        //Original height and width.
        mHeight = mBitmapFrame.getHeight();
        mWidth = mBitmapFrame.getWidth();
        
        //Initialize original and resized Rects.
        mOriginalRect = new Rect(getLeft(), getTop(), getLeft()+mWidth, getHeight()+mHeight);
        mResizedRect = new Rect(mOriginalRect);
        
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        mResizedRect.top = mOriginalRect.bottom - (int)(mHeight*(float)this.mPercent/100);
        
        /*
         * TODO:
         * Do we really need to draw the static frame bitmap on every draw?
         * Probably this can be optimized by drawing once.
         */
        canvas.drawBitmap(mBitmapFrame, null, mOriginalRect, mPaintFrame);
        
        /*
         * This is the actual resized "content" draw. 
         * Needs to be re-drawn every time.
         */
        canvas.drawBitmap(mBitmapContent, null, mResizedRect, mPaintContent);
        super.onDraw(canvas);
    }
    
    /**
     * Sets the new battery level.
     * @param newPercent The new percentage to set.
     */
    public void setPercent(int newPercent){
        this.mPercent = newPercent;
        invalidate();
    }
}
